package com.zfzs.post.service.impl;

import com.alibaba.nacos.common.util.Md5Utils;
import com.zfzs.post.common.bean.ResponseCode;
import com.zfzs.post.common.security.AuthorizationUser;
import com.zfzs.post.enums.TeamType;
import com.zfzs.post.exception.BadRequestException;
import com.zfzs.post.model.dto.*;
import com.zfzs.post.model.vo.*;
import com.zfzs.post.modules.agent.domain.*;
import com.zfzs.post.modules.agent.service.*;
import com.zfzs.post.modules.agent.service.dto.AgentDTO;
import com.zfzs.post.modules.agent.service.dto.AgentMoneyDTO;
import com.zfzs.post.modules.agent.service.mybatis.IAgentService;
import com.zfzs.post.modules.common.service.AgentContactService;
import com.zfzs.post.modules.domain.Picture;
import com.zfzs.post.page.JpaPageHelper;
import com.zfzs.post.service.*;
import com.zfzs.post.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 用户实现类
 *
 * @author: ck
 * @create: 2019-08-13 16:46
 **/
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private AgentService agentService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private AgentInfoService agentInfoService;
    @Autowired
    private JwtUserDetailsService jwtUserDetailsService;
    @Autowired
    private AgentBankService agentBankService;
    @Autowired
    private AgentVerifiedService agentVerifiedService;
    @Autowired
    private PictureService pictureService;
    @Autowired
    private SmsService smsService;
    @Autowired
    private AgentWithdrawPwdService agentWithdrawPwdService;
    @Autowired
    private AgentMoneyService agentMoneyService;
    @Autowired
    @Qualifier("jwtUserDetailsService")
    private UserDetailsService userDetailsService;

    @Autowired
    private AgentContactService agentContactService;

    @Autowired
    private IAgentService iAgentService;

    @Autowired
    private FlowService flowService;

    @Autowired
    private BenefitService benefitService;

    @Autowired
    private WithdrawOrderService orderService;

    @Override
    public AgentVO queryByPhone(String phone) {
        AgentDTO agentDTO = jwtUserDetailsService.getAgentInfo();
        AgentVO agentVO = CloneUtils.clone(agentDTO, AgentVO.class);
        AgentInfoVO agentInfoVO = CloneUtils.clone(agentDTO.getAgentInfo(), AgentInfoVO.class);
        AgentMoneyVO agentMoneyVO = CloneUtils.clone(agentDTO.getAgentMoney(), AgentMoneyVO.class);
        agentVO.setAgentInfo(agentInfoVO);
        //agentVO.setAgentMoney(agentMoneyVO);
        ImgVo imgVo = new ImgVo();
        imgVo.setUrl("https://i.loli.net/2019/07/25/5d395db5f18cf67374.jpg");
        agentVO.getAgentInfo().setHeadImg(imgVo);
        return agentVO;
    }

    @Override
    public AgentVO queryCacheById(Long id) {
        AgentDTO agentDTO = jwtUserDetailsService.getAgentInfo();
        AgentVO agentVO = CloneUtils.clone(agentDTO, AgentVO.class);
        return agentVO;
    }

    @Override
    public Map<String, String> refreshToken(RefreshTokenDTO dto) {
        Map<String, String> map = new HashMap<>();
        String token = dto.getToken();
        String jwtToken = jwtUserDetailsService.updateToken(token);
        map.put("token", jwtToken);
        return map;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, String> registePhone(UseRegisterDTO dto) {
        Map<String, String> map = new HashMap<>();
        String phone = dto.getPhone();
        String vCode = dto.getCode();
        String key = dto.getUuid();
        Long channelId = dto.getChannelId();
        //查询手机号码是否注册过
        Agent agentInfo = agentService.findByPhoneAndChannelId(phone, channelId);
        if (agentInfo != null) {
            throw new BadRequestException(ResponseCode.REPEAT_USER_FAIL);
        }
        //判断验证码
        String code = redisService.getCodeVal(key);
        if (StringUtils.isBlank(vCode)) {
            throw new BadRequestException("请输入验证码");
        }
        if (StringUtils.isEmpty(code)) {
            throw new BadRequestException(ResponseCode.V_CODE_TIME_OUT_FAIL);
        }
        if (!StringUtils.equals(vCode, code)) {
            throw new BadRequestException(ResponseCode.V_CODE_ERROR_FAIL);
        }

        //录入用户信息 除agent其它信息使用触发器增加
        Agent agent = insertAgent(dto, 1);
        //录入关联信息
        //agentContactService.updateContact(agent.getId(),agent.getPidId());
        agentContactService.updateContact(agent.getId(), agent.getPidId(), channelId);
        //生成登录令牌
        String token = jwtUserDetailsService.generateToken(agent.getId());
        redisService.delete(key);
        map.put("token", token);
        return map;

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Agent insertAgent(UseRegisterDTO dto, Integer userType) {
        //添加信息
        Agent agent = new Agent();
        agent.setPhone(dto.getPhone());
        agent.setUserType(userType);
        //验证推荐码
        Agent pidAgent = agentService.findById(dto.getPidId());
        if (pidAgent == null) {
            throw new BadRequestException("推荐码错误");
        }
        if (!pidAgent.getChannelId().equals(dto.getChannelId())) {
            throw new BadRequestException("您的推荐码不属于您的渠道");
        }
        //设置推荐码和渠道
        agent.setPidId(pidAgent.getId());
        agent.setChannelId(dto.getChannelId());

        //验证密码
        String confPwd = dto.getConfPwd();
        String pwd = dto.getPwd();
        if (!StringUtils.equals(confPwd, pwd)) {
            throw new BadRequestException(ResponseCode.PWD_NO_SAME_FAIL);
        }
        //设置密码 生成10位数字随机盐值
        String salt = StringUtils.getRandomString(10);
        agent.setSalt(salt);
        //密码修改
        String realPwd = AesUtil.aesEncrypt(dto.getPwd() + salt, AesUtil.encodeRules);
        agent.setPassword(realPwd);
        //添加id
        Long id = verifyId(Long.valueOf(StringUtils.getRandomNumberString(8)));
        agent.setId(id);
        //增加基础信息
        Agent agentInfo = agentService.create(agent);

        if (agentInfo == null) {
            throw new BadRequestException("新增用户基础信息失败");
        }
        return agentInfo;
    }

    @Override
    public void loginOut(HttpServletRequest request) {
        String token = jwtUserDetailsService.getToken(request);
        jwtUserDetailsService.clearToken(token);
    }

    @Override
    public Long verifyId(Long id) {
        Agent agent = agentService.findById(id);
        if (agent != null) {
            id = Long.valueOf(StringUtils.getRandomNumberString(8));
            verifyId(id);
        }
        return id;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void forgetPwd(ForgetPwdDTO dto) {
        String phone = dto.getPhone();
        String vCode = dto.getCode();
        String cfmPwd = dto.getCfmPwd();
        String pwd = dto.getPwd();
        String key = dto.getUuid();
        Long channelId = dto.getChannelId();
        //查找验证码缓存
        String code = redisService.getCodeVal(key);
        if (StringUtils.isEmpty(key)) {
            throw new BadRequestException(ResponseCode.V_CODE_TIME_OUT_FAIL);
        }
        if (!StringUtils.equals(vCode, code)) {
            throw new BadRequestException(ResponseCode.V_CODE_ERROR_FAIL);
        }
        if (!StringUtils.equals(cfmPwd, pwd)) {
            throw new BadRequestException(ResponseCode.PWD_NO_SAME_FAIL);
        }
        Agent agent = agentService.findByPhoneAndChannelId(phone, channelId);
        if (agent == null) {
            throw new BadRequestException(ResponseCode.NO_USER_FAIL);
        }
        //修改密码操作
        agent.setPassword(pwd);
        updatePassword(CloneUtils.clone(agent, AgentDTO.class));
        redisService.delete(key);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePwd(UpdatePwdDTO dto) {
        String cfmPwd = dto.getCfmPwd(); //确认密码
        String pwd = dto.getPwd(); //密码
        String originalPwd = dto.getOriginalPwd(); //原始密码
        //校验验证码
        String vCode = dto.getCode();
        String key = dto.getUuid();
        //查找验证码缓存
        String code = redisService.getCodeVal(key);
        if (StringUtils.isEmpty(key)) {
            throw new BadRequestException(ResponseCode.V_CODE_TIME_OUT_FAIL);
        }
        if (!StringUtils.equals(vCode, code)) {
            throw new BadRequestException(ResponseCode.V_CODE_ERROR_FAIL);
        }
        AgentDTO agent = jwtUserDetailsService.getAgentInfo();
        if (!StringUtils.equals(cfmPwd, pwd)) {
            throw new BadRequestException(ResponseCode.PWD_NO_SAME_FAIL);
        }
        if (!isPwdCorrect(agent, originalPwd)) {
            throw new BadRequestException(ResponseCode.PWD_ORIGINAL_ERROR_FAIL);
        }
        //修改密码操作
        agent.setPassword(pwd);
        updatePassword(agent);
        redisService.delete(key);
    }

    @Override
    public boolean isAgentById(Long id) {
        Agent agent = agentService.findById(id);
        if (agent == null) {
            return false;
        }
        return true;
    }

    @Override
    public boolean isPwdCorrect(AgentDTO agent, String pwd) {
        String salt = agent.getSalt();
        if (!agent.getPassword().equals(AesUtil.aesEncrypt(pwd + salt, AesUtil.encodeRules))) {
            return false;
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePassword(AgentDTO dto) {
        //生成10位数字随机盐值
        String salt = StringUtils.getRandomString(10);
        dto.setSalt(salt);
        Timestamp time2 = new Timestamp(System.currentTimeMillis());
        dto.setUpdatePasswordTime(time2);
        //密码修改
        String pwd = AesUtil.aesEncrypt(dto.getPassword() + salt, AesUtil.encodeRules);
        dto.setPassword(pwd);
        agentService.update(CloneUtils.clone(dto, Agent.class));
    }

    @Override
    public Agent isUserPre() {
        Long id = SecurityUtils.getUserId();
        Agent agent = agentService.findById(id);
        if (agent == null) {
            throw new BadRequestException(ResponseCode.NO_USER_FAIL);
        }
        return agent;
    }

    @Override
    public Map<String, String> loginPWd(AuthorizationUser authorizationUser) {
        Map<String, String> map = new HashMap<>();
        Long channelId = authorizationUser.getChannelId();
        String phone = authorizationUser.getPhone();
        Agent agent = agentService.findByPhoneAndChannelId(phone, channelId);
        if (agent == null) {
            throw new BadRequestException("账号不存在");
        }
        if (agent.getIsEnabled()) {
            throw new BadRequestException(ResponseCode.USER_ENABLED_FAIL);
        }
        String salt = agent.getSalt();


        String checkPwd = AesUtil.aesEncrypt(authorizationUser.getPassword() + salt, AesUtil.encodeRules);

        if (!agent.getPassword().equals(checkPwd)) {
            throw new BadRequestException("密码错误");
        }

        //用户授权
        String agentId = Long.toString(agent.getId());
        userDetailsService.loadUserByUsername(agentId);
        // 生成令牌
        final String token = jwtUserDetailsService.generateToken(agent.getId());
        map.put("token", token);
        return map;
    }

    @Override
    public Map<String, String> loginSmsCode(LoginCodeDTO dto) {
        Map<String, String> map = new HashMap<>();
        String phone = dto.getPhone();
        String vCode = dto.getCode();
        String key = dto.getUuid();
        Long channelId = dto.getChannelId();
        Agent agent = agentService.findByPhoneAndChannelId(phone, channelId);
        if (agent == null) {
            throw new BadRequestException("账号不存在");
        }
        if (agent.getIsEnabled()) {
            throw new BadRequestException(ResponseCode.USER_ENABLED_FAIL);
        }
        //查询验证码
        String code = redisService.getCodeVal(key);
        if (StringUtils.isEmpty(code)) {
            throw new BadRequestException(ResponseCode.V_CODE_TIME_OUT_FAIL);
        }
        if (!StringUtils.equals(vCode, code)) {
            throw new BadRequestException(ResponseCode.V_CODE_ERROR_FAIL);
        }
        // 生成令牌
        final String token = jwtUserDetailsService.generateToken(agent.getId());
        redisService.delete(key);
        map.put("token", token);
        return map;
    }


    @Override
    public Map<String, Object> getUserInfo() {
        Map<String, Object> map = new HashMap<>();
        AgentDTO agent = jwtUserDetailsService.getAgentInfo();
        String bankNo = "";
        String name = "";
        String cardNo = "";
        String bankName = "";
        Long id = agent.getId();
        //头像
        Long imgId = agent.getAgentInfo().getHeadImgId();
        Picture picture = pictureService.findById(imgId);
        map.put("headImgUrl", picture.getUrl());
        AgentBank bank = agentBankService.findById(id);
        if (bank != null) {
            bankNo = bank.getBankNo();
            bankName = bank.getBankName();

        }
        AgentVerified verified = agentVerifiedService.findById(id);
        if (verified != null) {
            cardNo = verified.getCardNo();
            name = verified.getCardName();
        }
        map.put("bankName", bankName);
        //姓名
        map.put("name", name);
        //手机号码
        String phone = agent.getPhone();
        map.put("phone", phone);
        //结算卡号
        map.put("bankNo", bankNo);
        //身份证号码
        map.put("cardNo", cardNo);
        //推荐码
        map.put("agentId", id);
        //客户经理
        map.put("pidId", agent.getPidId());
        map.put("isEffective", agent.getIsEffective());
        return map;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void verified(VerifiedDTO dto) {
        String bankNo = dto.getBankNo();
        Long cardPositImgId = dto.getCardPositImgId();
        Long cardBackImgId = dto.getCardBackImgId();
        String cardName = dto.getCardName();
        String cardNo = dto.getCardNo();
        String pwd = dto.getPwd();
        String cfmPwd = dto.getCfmPwd();
        String uuid = dto.getUuid();
        String vCode = dto.getCode();
        String bankName = dto.getBankName();
        String phone = dto.getPhone();
        AgentDTO agent = jwtUserDetailsService.getAgentInfo();
        Long agentId = agent.getId();
        if (agent.getIsEffective() == 1 || agent.getIsEffective() == 2) {
            throw new BadRequestException("正在审核或者已经完成认证");
        }
        smsService.verifiedCode(uuid, vCode);
        if (!StringUtils.equals(cfmPwd, pwd)) {
            throw new BadRequestException(ResponseCode.PWD_NO_SAME_FAIL);
        }
        //校验身份证
        if (!IDCard.IDCardVerification(cardNo)) {
            throw new BadRequestException("请输入正确的身份证号码");
        }
        /*************** 实名认证数据录入 **************/
        updateBank(agentId, bankNo, bankName, phone);
        AgentVerified verified = new AgentVerified();
        verified.setCardBackImgId(cardBackImgId);
        verified.setCardName(cardName);
        verified.setCardNo(cardNo);
        verified.setCardPositImgId(cardPositImgId);
        verified.setId(agentId);
        agentVerifiedService.update(verified);
        updateWithdrawPwd(agentId, pwd);
        Agent agnetInfo = agentService.findById(agent.getId());
        agnetInfo.setIsEffective(2);
        agentService.update(agnetInfo);
        //删除缓存
        redisService.delete(uuid);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBank(Long agentId, String bankNo, String bankName, String phone) {
        //校验手机号码
        Agent agent = agentService.findById(agentId);
        AgentBank bank = new AgentBank();
        if (StringUtils.isNotBlank(phone)) {
            int count = iAgentService.findByPhoneAndChannel(phone, agent.getChannelId());
            if (count > 0) {
                throw new BadRequestException("此预留手机号码已经被实名认证");
            } else {
                bank.setPhone(phone);
            }
        }
        //验证银行卡信息
        Map<String, Object> map = BankUtil.getBankCodeAndName(bankNo);
        String bankCode = map.get("bankCode").toString();
        bank.setBankCode(bankCode);
        bank.setBankImgId(1L);
        bank.setBankName(bankName);
        bank.setBankNo(bankNo);
        bank.setBankId(agentId);
        agentBankService.update(bank);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateWithdrawPwd(Long agentId, String pwd) {
        AgentWithdrawPwd withdrawPwd = new AgentWithdrawPwd();
        withdrawPwd.setId(agentId);
        //生成10位数字随机盐值
        String salt = StringUtils.getRandomString(10);
        String password = AesUtil.aesEncrypt(pwd + salt, AesUtil.encodeRules);
        withdrawPwd.setPwd(password);
        withdrawPwd.setSalt(salt);
        agentWithdrawPwdService.update(withdrawPwd);
    }

    @Override
    public void updateWithdrawPwd(UpdatePwdDTO dto) {
        String cfmPwd = dto.getCfmPwd(); //确认密码
        String pwd = dto.getPwd(); //密码
        String originalPwd = dto.getOriginalPwd(); //原始密码
        //校验验证码
        String vCode = dto.getCode();
        String key = dto.getUuid();
        //查找验证码缓存
        String code = redisService.getCodeVal(key);
        if (StringUtils.isEmpty(key)) {
            throw new BadRequestException(ResponseCode.V_CODE_TIME_OUT_FAIL);
        }
        if (!StringUtils.equals(vCode, code)) {
            throw new BadRequestException(ResponseCode.V_CODE_ERROR_FAIL);
        }
        AgentDTO agent = jwtUserDetailsService.getAgentInfo();
        if (!StringUtils.equals(cfmPwd, pwd)) {
            throw new BadRequestException(ResponseCode.PWD_NO_SAME_FAIL);
        }
        //校验密码
        AgentWithdrawPwd withdrawPwd = agentWithdrawPwdService.findById(agent.getId());
        if (withdrawPwd == null) {
            throw new BadRequestException("没有查询到体现信息");
        }
        String salt = withdrawPwd.getSalt();
        if (!withdrawPwd.getPwd().equals(AesUtil.aesEncrypt(originalPwd + salt, AesUtil.encodeRules))) {
            throw new BadRequestException("提现密码错误");
        }
        //修改密码操作
        updateWithdrawPwd(agent.getId(), pwd);
        redisService.delete(key);
    }

    @Override
    public void forgetWithdrawPwd(ForgetPwdDTO dto) {
        String phone = dto.getPhone();
        String vCode = dto.getCode();
        String cfmPwd = dto.getCfmPwd();
        String pwd = dto.getPwd();
        String key = dto.getUuid();
        Long channelId = dto.getChannelId();
        //查找验证码缓存
        String code = redisService.getCodeVal(key);
        if (StringUtils.isEmpty(key)) {
            throw new BadRequestException(ResponseCode.V_CODE_TIME_OUT_FAIL);
        }
        if (!StringUtils.equals(vCode, code)) {
            throw new BadRequestException(ResponseCode.V_CODE_ERROR_FAIL);
        }
        if (!StringUtils.equals(cfmPwd, pwd)) {
            throw new BadRequestException(ResponseCode.PWD_NO_SAME_FAIL);
        }
        Agent agent = agentService.findByPhoneAndChannelId(phone, channelId);
        if (agent == null) {
            throw new BadRequestException(ResponseCode.NO_USER_FAIL);
        }
        //修改密码操作
        agent.setPassword(pwd);
        //修改密码操作
        updateWithdrawPwd(agent.getId(), pwd);
        redisService.delete(key);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSettleInfo(UpdateSettleDTO dto) {
        String bankName = dto.getBankName();
        String bankNo = dto.getBankNo();
        String cardNo = dto.getCardNo();
        String uuid = dto.getUuid();
        String vCode = dto.getCode();
        String phone = dto.getPhone();
        AgentDTO agent = jwtUserDetailsService.getAgentInfo();
        Long agentId = agent.getId();
        //校验验证码
        smsService.verifiedCode(uuid, vCode);
        if (agent.getIsEffective() == 0) {
            throw new BadRequestException("您还未完成实名认证操作");
        }
        //校验身份证
        AgentVerified agentVerified = agentVerifiedService.findById(agentId);
        if (!StringUtils.equals(agentVerified.getCardNo(), cardNo)) {
            throw new BadRequestException("身份证号码错误");
        }
        /************ 修改认证数据 ***********/
        AgentBank bank = agentBankService.findById(agent.getId());
        String agentPhone = bank.getPhone();
        if (!StringUtils.equals(agentPhone, phone)) {
            throw new BadRequestException("预留手机号码不一致");
        }
        updateBank(agentId, bankNo, bankName, null);
        redisService.delete(uuid);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateIDCardNo(UpdateIDCardNoDTO dto) {
        String cardNo = dto.getCardNo();
        String uuid = dto.getUuid();
        String vCode = dto.getCode();
        //校验验证码
        smsService.verifiedCode(uuid, vCode);
        AgentDTO agent = jwtUserDetailsService.getAgentInfo();
        if (agent.getIsEffective() == 0) {
            throw new BadRequestException("您还未完成实名认证操作");
        }
        Long agentId = agent.getId();
        //校验身份证
        AgentVerified verified = new AgentVerified();
        verified.setCardNo(cardNo);
        verified.setId(agentId);
        agentVerifiedService.update(verified);
        redisService.delete(uuid);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePhone(UpdatePhoneDTO dto) {
        String phone = dto.getPhone();
        String uuid = dto.getUuid();
        String vCode = dto.getCode();
        AgentDTO agent = jwtUserDetailsService.getAgentInfo();
        //查询手机号是否存在
        if (agent.getPhone().equals(phone)) {
            throw new BadRequestException("手机号码和本人手机号码相同");
        }
        Agent agentByPhone = agentService.findByPhoneAndChannelId(phone, agent.getChannelId());
        if (agentByPhone != null) {
            throw new BadRequestException(ResponseCode.REPEAT_USER_FAIL);
        }
        //校验验证码
        smsService.verifiedCode(uuid, vCode);
        AgentDTO agentDto = jwtUserDetailsService.getAgentInfo();
        Long agentId = agentDto.getId();
        Agent agentInfo = new Agent();
        agentInfo.setId(agentId);
        agentInfo.setPhone(phone);
        agentService.update(agentInfo);
        redisService.delete(uuid);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateIDCardName(UpdateIDCardNameDTO dto) {
        String cardName = dto.getCardName();
        String uuid = dto.getUuid();
        String vCode = dto.getCode();
        //校验验证码
        smsService.verifiedCode(uuid, vCode);
        AgentDTO agentDto = jwtUserDetailsService.getAgentInfo();
        if (agentDto.getIsEffective() == 0) {
            throw new BadRequestException("您还未完成实名认证操作");
        }
        Long agentId = agentDto.getId();
        AgentVerified verified = new AgentVerified();
        verified.setCardName(cardName);
        verified.setId(agentId);
        agentVerifiedService.update(verified);
        redisService.delete(uuid);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void withdrawMoney(WithdrawDTO dto) {
        AgentDTO agent = jwtUserDetailsService.getAgentInfo();
        Long channelId = agent.getChannelId();
        BigDecimal money = dto.getMoney();
        String pwd = dto.getPwd();
        Long agnetId = agent.getId();
        //校验密码
        AgentWithdrawPwd withdrawPwd = agentWithdrawPwdService.findById(agnetId);
        if (withdrawPwd == null) {
            throw new BadRequestException("没有查询到体现信息");
        }
        String salt = withdrawPwd.getSalt();
        if (!withdrawPwd.getPwd().equals(AesUtil.aesEncrypt(pwd + salt, AesUtil.encodeRules))) {
            throw new BadRequestException("提现密码错误");
        }
        if (money.compareTo(new BigDecimal(0.00)) == -1) {
            throw new BadRequestException("提现金额必须大于0");
        }
        if (agent.getIsEffective() == 0) {
            throw new BadRequestException("您还未完成实名认证操作");
        }
        //查询银行卡信息
        AgentBank bank = agentBankService.findById(agnetId);
        if (bank == null) {
            throw new BadRequestException("未查询到银行卡信息");
        }
        //查询余额 余额是否够用
        AgentMoneyDTO agentMoney = agent.getAgentMoney();
        Long version = agentMoney.getVersion();
        //可用余额
        BigDecimal usableMoney = agentMoney.getUsableMoney();
        if (usableMoney.compareTo(money) == -1) {
            throw new BadRequestException("可用余额不足，提现失败");
        }
        /***************************** 开始提现流程 ************************/
        //减少可用余额 增加冻结金额
        int count = agentMoneyService.withdrawMoney(agnetId, money, version);
        if (count == 0) {
            throw new BadRequestException("提现失败");
        }
        //录入流水信息
        WithdrawOrder order = new WithdrawOrder();
        order.setAgentId(agnetId);
        order.setChannelId(channelId);
        order.setAllAmount(money);
        order.setToAmount(money);
        order.setCurrentAmount(usableMoney);
        order.setAfterAmount(usableMoney.subtract(money));
        orderService.create(order);
    }

    @Override
    public Map<String, Object> agetWithdrawInfow() {
        Map<String, Object> map = new HashMap<>();
        AgentDTO agent = jwtUserDetailsService.getAgentInfo();
        Long id = agent.getId();
        //查询银行卡信息
        AgentBank bank = agentBankService.findById(id);
        Picture picture = pictureService.findById(bank.getBankImgId());
        AgentMoney agentMoney = agentMoneyService.findById(id);
        if (StringUtils.isBlank(bank.getBankName())) {
            throw new BadRequestException("请添加银行卡信息");
        }
        map.put("bankImgUrl", picture.getUrl());
        map.put("bankName", bank.getBankName());
        map.put("usableMoney", MathUtils.formatToNumber(agentMoney.getUsableMoney()));
        map.put("rate", "8%");
        map.put("fee", "2");
        return map;
    }

    @Override
    public Map<String, Object> getSettCardInfo() {
        Map<String, Object> map = new HashMap<>();
        AgentDTO agent = jwtUserDetailsService.getAgentInfo();
        Long id = agent.getId();
        //查询银行卡信息
        AgentBank bank = agentBankService.findById(id);
        map.put("bank", bank);
        AgentVerified verified = agentVerifiedService.findById(id);
        map.put("cardName", verified.getCardName());
        map.put("cardNo", verified.getCardNo());
        map.put("phone", agent.getPhone());
        return map;
    }

    @Override
    public void updateSettCardInfo(BankInfoDTO dto) {
        AgentDTO agent = jwtUserDetailsService.getAgentInfo();
        //校验验证码
        String vCode = dto.getCode();
        String key = dto.getUuid();
        String code = redisService.getCodeVal(key);
        Integer isEffective = agent.getIsEffective();
        if (isEffective == 0) {
            throw new BadRequestException("您还没有实名认证");
        }
        //查找验证码缓存
        if (StringUtils.isEmpty(code)) {
            throw new BadRequestException(ResponseCode.V_CODE_TIME_OUT_FAIL);
        }
        if (!StringUtils.equals(vCode, code)) {
            throw new BadRequestException(ResponseCode.V_CODE_ERROR_FAIL);
        }
        Long id = agent.getId();
        //查询银行卡信息
        AgentBank bank = agentBankService.findById(id);
        //查询实名认证
        AgentVerified verified = agentVerifiedService.findById(id);
        if (bank == null || verified == null) {
            throw new BadRequestException("没有查询到以后哪个科或者实名认证信息");
        }
        //修改操作
        bank.setBankNo(dto.getBankNo());
        bank.setBankName(dto.getBankName());
        agentBankService.update(bank);
        verified.setCardNo(dto.getCardNo());
        agentVerifiedService.update(verified);
        redisService.delete(key);
    }

    @Override
    public Map<String, Object> getWithdrawList() {
        Map<String, Object> map = new HashMap<>();
        AgentDTO agent = jwtUserDetailsService.getAgentInfo();
        Long id = agent.getId();
        List<WithdrawListVO> list = orderService.withdrawList(id);
        map.put("list", list);
        return map;
    }

    @Override
    public Map<String, Object> getSubAgentList() {
        Map<String, Object> map = new HashMap<>();
        AgentDTO agent = jwtUserDetailsService.getAgentInfo();
        List<Agent> list = agentService.findByPidId(agent.getId());
        List<AgentVO> collect = list.stream().map(e -> {
            AgentVO clone = CloneUtils.clone(e, AgentVO.class);
            clone.setAgentInfo(CloneUtils.clone(e.getAgentInfo(), AgentInfoVO.class));
            return clone;
        }).collect(Collectors.toList());
        map.put("list", collect);
        return map;
    }

    @Override
    public Map<String, Object> getAgentListByKeywords(QueryAgnetListDTO dto) {
        Map<String, Object> map = new HashMap<>();
        String keywords = dto.getQuery();
        String partner = dto.getType();
        AgentDTO agent = jwtUserDetailsService.getAgentInfo();
        List<Long> ids = agentContactService.findAllTeamIdsExceptSelf(agent.getId(), agent.getChannelId());
        List<Agent> list = agentService.getAgentListByKeywords(keywords, ids);
        List<QueryAgentVO> collect = list.stream()
                .map(e -> {
                    QueryAgentVO clone = CloneUtils.clone(e, QueryAgentVO.class);
                    Long id = e.getId();

                    Long pidId = e.getPidId();
                    //查询实名认证信息
                    AgentVerified agentVerified = agentVerifiedService.findByAgentId(id);
                    if (agentVerified == null) {
                        clone.setName(e.getAgentInfo().getNickName());
                    } else {
                        clone.setName(agentVerified.getCardName());
                    }
                    //查询是直属下的信息
                    clone.setIsDirectly(agentService.isDirectly(id, pidId));
                    return clone;
                }).collect(Collectors.toList());
        map.put("list", collect);
        return map;
    }

    @Override
    public Map<String, Object> getAgentByIdsList(QueryAgnetTypeListDTO dto) {
        Map<String, Object> map = new HashMap<>();
        String types = dto.getType();
        AgentDTO agent = jwtUserDetailsService.getAgentInfo();
        List<Long> ids;

        if (TeamType.DIRECTLY.equals(types)) {
            ids = agentContactService.findDirectlyIds(agent.getId(), agent.getChannelId());
        } else {
            ids = agentContactService.findAllTeamIdsExceptSelf(agent.getId(), agent.getChannelId());
        }
        List<Agent> list = agentService.getAgentByIdsList(ids);
        List<QueryAgentVO> collect = list.stream()
                .map(e -> {
                    QueryAgentVO clone = CloneUtils.clone(e, QueryAgentVO.class);
                    Long id = e.getId();
                    Long pidId = e.getPidId();
                    //查询实名认证信息
                    AgentVerified agentVerified = agentVerifiedService.findByAgentId(id);
                    if (agentVerified == null) {
                        clone.setName(e.getAgentInfo().getNickName());
                    } else {
                        clone.setName(agentVerified.getCardName());
                    }
                    //查询是直属下的信息
                    clone.setIsDirectly(agentService.isDirectly(id, pidId));
                    return clone;
                }).collect(Collectors.toList());
        map.put("list", collect);
        return map;
    }

    @Override
    public Map<String, Object> getAgentPageList(QueryAgentPageListDTO dto) {
        Map<String, Object> map = new HashMap<>();
        AgentDTO agent = jwtUserDetailsService.getAgentInfo();
        Long id = agent.getId();
        //盟友类型 DIRECT:直属 PARTNER：合伙人
        String agnetType = dto.getAgentType();
        String dateType = dto.getDateType();
        String dir = dto.getDir();
        String store = dto.getStore();
        Long channelId = agent.getChannelId();

        dto.setAgentId(id);
        dto.setChannelId(channelId);
        if (StringUtils.isNotEmpty(dateType)) {
            Map<String, String> day = DateStrUtils.getStartAndEndDate(dateType);
            if (day == null) {
                throw new BadRequestException("维度类型参数错误");
            }
            dto.setStartDate(day.get("startDate"));
            dto.setEndDate(day.get("endDate"));
        }
        if (StringUtils.isNotEmpty(agnetType)) {
            if (TeamType.DIRECTLY.equals(agnetType)) {
                //查询直属
                List<Long> ids = agentContactService.findDirectlyIds(id, channelId);
                dto.setAgentIds(ids);
            } else if ("ALL".equals(agnetType)) {
                //查询所有
                List<Long> ids = agentContactService.findAllTeamIds(id, channelId);
                dto.setAgentIds(ids);
            } else if ("PARTNER".equals(agnetType)) {
                //查询合伙人
                List<Long> ids = agentContactService.findPartnerTeam(id, channelId);
                dto.setAgentIds(ids);
            } else {
                throw new BadRequestException("错误的盟友类型");
            }
        } else {
            //查询所有
            List<Long> ids = agentContactService.findAllTeamIds(id, channelId);
            dto.setAgentIds(ids);
        }
        if (StringUtils.isNotEmpty(store)) {
            if (StringUtils.isEmpty(dir)) {
                throw new BadRequestException("降序升序参数错误");
            }
        }
        JpaPageHelper page = iAgentService.findAgentPageList(dto);
        map.put("page", page);
        return map;
    }

    @Override
    public void updateheadImg(IdDTO dto) {
        AgentDTO agent = jwtUserDetailsService.getAgentInfo();
        Long agentId = agent.getId();
        Long id = dto.getId();
        AgentInfo agentInfo = agentInfoService.findById(agentId);
        agentInfo.setHeadImgId(id);
        agentInfoService.update(agentInfo);
    }

    @Override
    public AgentMineInfoVO myIndexInfo() {
        AgentMineInfoVO vo = new AgentMineInfoVO();
        AgentDTO agent = jwtUserDetailsService.getAgentInfo();
        AgentVerified verified = agentVerifiedService.findById(agent.getId());
        //id
        vo.setAgentId(agent.getId());
        //查询图片
        Picture p = pictureService.findById(agent.getAgentInfo().getHeadImgId());
        vo.setHeadImgUrl(p.getUrl());
        //姓名
        vo.setAgentName(verified.getCardName());

        //手机号码
        vo.setPhone(agent.getPhone());

        Long id = agent.getId();
        //任务完成率
        vo.setTaskRate("0%");
        //任务奖励

        vo.setTeamEeward("0.00");

        //钱包余额
        AgentMoney money = agentMoneyService.findById(id);
        BigDecimal usableMoney = money.getUsableMoney();
        vo.setUsableMoney(MathUtils.formatToNumber(usableMoney));
        //累计收益
        BigDecimal totalMoney = money.getTotalMoney();
        vo.setTotalEeward(MathUtils.formatToNumber(totalMoney));
        vo.setIsEffective(agent.getIsEffective());
        //自营分润
        vo.setSelfEeward(MathUtils.formatToNumber(benefitService.getSelfBenefit(agent.getId())));
        //团队
        vo.setTeamEeward(MathUtils.formatToNumber(benefitService.getTeamBenefit(agent.getId())));

        //激活奖励
        BigDecimal sumActivIncome = flowService.getSumActivIncome(agent.getId());
        vo.setActivEeward(MathUtils.formatToNumber(sumActivIncome));

        //其他收益
        BigDecimal sumOtherIncome = flowService.getSumOtherIncome(agent.getId());
        vo.setOtherEward(MathUtils.formatToNumber(sumOtherIncome));

        vo.setLeastEeward("0.00");
        vo.setTaskEeward("0.00");
        return vo;
    }

    @Override
    public void addAgentByUpper(AddAgentDTO addAgentDTO) {
        AgentDTO info = jwtUserDetailsService.getAgentInfo();

        String phone = addAgentDTO.getPhone();
        Agent byPhoneAndChannelId = agentService.findByPhoneAndChannelId(phone, info.getChannelId());
        if (byPhoneAndChannelId != null) {
            throw new BadRequestException("该账号已存在");
        }

        Long pid = addAgentDTO.getAgentId();

        if (StringUtils.isBlank(addAgentDTO.getAgentType())) {
            throw new BadRequestException("合伙人类型不能为空");
        } else if (TeamType.DIRECTLY.equals(addAgentDTO.getAgentType())) {
            pid = info.getId();
        } else if (TeamType.PARTNER.equals(addAgentDTO.getAgentType()) && pid == null) {
            throw new BadRequestException("上级id不能为空");
        } else {
            throw new BadRequestException("合伙人类型错误");
        }

        String password = addAgentDTO.getPassword();

        Long channelId = info.getChannelId();
        //判断验证码
        UseRegisterDTO dto = new UseRegisterDTO();

        String pwd = Md5Utils.getMD5(password.getBytes());

        dto.setPhone(phone);
        dto.setPwd(pwd);
        dto.setConfPwd(pwd);
        dto.setPidId(pid);

        dto.setChannelId(channelId);

        //录入用户信息 除agent其它信息使用触发器增加
        Agent agent = insertAgent(dto, 1);
        //录入关联信息
        agentContactService.updateContact(agent.getId(), agent.getPidId(), channelId);
        //发送短信
        String content = "TEST!TEST!您的注册账号为" + phone + ",密码为" + password + "。";
        smsService.sendMessage(info.getChannelId(), phone, content);

    }

    @Override
    public Map<String, Object> getTeamList() {
        Map<String, Object> map = new HashMap<>();
        List<TeamListVO> list = new LinkedList<>();
        TeamListVO vo = new TeamListVO();
        vo.setKey(TeamType.DIRECTLY);
        vo.setValue("直营");
        list.add(vo);
        TeamListVO vo1 = new TeamListVO();
        vo1.setKey(TeamType.PARTNER);
        vo1.setValue("合伙人");
        list.add(vo1);
        map.put("list", list);
        return map;
    }

    @Override
    public Map<String, Object> getAllChild() {
        AgentDTO info = jwtUserDetailsService.getAgentInfo();

        List<Long> ids = agentContactService.findAllTeamIdsExceptSelf(info.getId(), info.getChannelId());
        List<Agent> list = agentService.getAgentByIdsList(ids);
        List<QueryAgentVO> collect = list.stream()
                .map(e -> {
                    QueryAgentVO clone = CloneUtils.clone(e, QueryAgentVO.class);
                    Long id = e.getId();
                    //查询实名认证信息
                    AgentVerified agentVerified = agentVerifiedService.findByAgentId(id);
                    if (agentVerified == null) {
                        clone.setName(e.getAgentInfo().getNickName());
                    } else {
                        clone.setName(agentVerified.getCardName());
                    }
                    //查询是直属下的信息
                    clone.setIsDirectly(true);
                    return clone;
                }).collect(Collectors.toList());

        return new HashMap<String, Object>() {{
            put("list", collect);
        }};
    }

    @Override
    public Map<String, Object> getTeamRankPage(QueryTeamRankPageDTO dto) {
        Map<String, Object> map = new HashMap<>();
        AgentDTO agent = jwtUserDetailsService.getAgentInfo();
        Long id = agent.getId();
        //盟友类型 DIRECT:直属 PARTNER：合伙人
        String agentType = dto.getAgentType();
        String dateType = dto.getDateType();
        Long channelId = agent.getChannelId();

        dto.setAgentId(id);
        dto.setChannelId(channelId);
        if (StringUtils.isNotEmpty(dateType)) {
            Map<String, String> day = DateStrUtils.getStartAndEndDate(dateType);
            if (day == null) {
                throw new BadRequestException("维度类型参数错误");
            }
            dto.setStartDate(day.get("startDate"));
            dto.setEndDate(day.get("endDate"));
        } /*else {
            //默认本月时间
            Map<String, String> day = DateStrUtils.getStartAndEndDate(DayType.TO_MONTH);
            if (day == null) {
                throw new BadRequestException("维度类型参数错误");
            }
            dto.setStartDate(day.get("startDate"));
            dto.setStartDate(day.get("endDate"));
        }*/
        if (StringUtils.isNotEmpty(agentType)) {
            if (TeamType.DIRECTLY.equals(agentType)) {
                //查询直属
                List<Long> ids = agentContactService.findDirectlyIds(id, channelId);
                dto.setAgentIds(ids);
            } else if ("ALL".equals(agentType)) {
                //查询所有
                List<Long> ids = agentContactService.findAllTeamIdsExceptSelf(id, channelId);
                dto.setAgentIds(ids);
            } else if ("PARTNER".equals(agentType)) {
                //查询合伙人
                List<Long> ids = agentContactService.findPartnerTeam(id, channelId);
                dto.setAgentIds(ids);
            } else {
                throw new BadRequestException("错误的盟友类型");
            }
        } else {
            //查询所有
            List<Long> ids = agentContactService.findAllTeamIdsExceptSelf(id, channelId);
            dto.setAgentIds(ids);
        }
        JpaPageHelper page = iAgentService.getTeamRankPage(dto);
        map.put("totalCount", page.getTotalCount());
        map.put("list", page.getResult());
        return map;
    }
}
